/*
 * 本代码是用来进行串口解析默认为Arduino平台 可移植至其他平台
 * 本代码中 用Serial.print作为串口输出 若非Arduino平台，更换成相应UART函数输出即可
 */
#include "cmd.h"
cmdNode cmd_list[CMD_LIST_SIZE];
void cmd_register(const char cmd_name[CMD_LENGTH],const char cmd_message[CMD_MESSAGE_LENGTH],cmd_handler func_name,int hash_node);

/*help命令*/
int cmd_help(void){
    for (int i = 0; i < CMD_LIST_SIZE; i++)
    {
        if (strcmp(cmd_list[i].cmd_name,""))//根据名字查找
        {
            Serial.print(cmd_list[i].cmd_name);
            Serial.print("\t----\t");
            Serial.println(cmd_list[i].cmd_message);
        }
    }
    return 0;
}

/*用户自定义函数区*/

int cmd1(void){
    Serial.println("cmd1 OK!");
    return 0;
}

/*用户初始化 注册cmd处*/
void cmd_init(void){
    
    /*命令在此添加*/
    cmd_register("help","function describe",&cmd_help,0);
    cmd_register("cmd1","cmd1_test",&cmd1,1);//cmd名称 cmd描述信息 cmd函数指针 哈希地址
}


/*系统函数区 用户无需关心 记得更改Serial.print输出函数即可*/
void cmd_register(const char cmd_name[CMD_LENGTH],const char cmd_message[CMD_MESSAGE_LENGTH],cmd_handler func_name,int hash_node){
    strcpy(cmd_list[hash_node].cmd_name,cmd_name);
    strcpy(cmd_list[hash_node].cmd_message,cmd_message);
    cmd_list[hash_node].hander = func_name;
    cmd_list[hash_node].node_hash = hash_node;
}
//查询函数 ex:cmd_parsing("cmd1");
void cmd_parsing(char name[CMD_LENGTH]){
    if(name[0] != '\n')name = strtok(name,"\n");//去除回车符
    else{
        Serial.print("\n");//接受空cmd时进行换行
        return ;
        }
    for (int i = 0; i < CMD_LIST_SIZE; i++)
    {
        if (!strcmp(cmd_list[i].cmd_name,name))//根据名字查找
        {
            cmd_list[i].hander();
            return ;
        }
    }
    Serial.println("not found cmd!\nYou can use 'help' to get all available command!");//可自行换成串口输出
}

// //hash table
// //初始化哈希表
// table t;
// void initHashTable(table* t)
// {
//     int i;
//     if (t == NULL)return;

//     for (i = 0; i < CMD_LIST_SIZE; ++i) {
//         t->bucket[i].key = NULL;
//         t->bucket[i].value = NULL;
//         t->bucket[i].next = NULL;
//     }
// }

// //释放哈希表
// void freeHashTable(table* t)
// {
//     int i;
//     entry* e,*ep;
//     if (t == NULL)return;
//     for (i = 0; i<CMD_LIST_SIZE; ++i) {
//         e = &(t->bucket[i]);
//         while (e->next != NULL) {
//             ep = e->next;
//             e->next = ep->next;
//             free(ep->key);
//             free(ep->value);
//             free(ep);
//         }
//     }
// }

// //哈希散列方法函数
// int keyToIndex(const char* key)
// {
//     int index , len , i;
//     if (key == NULL)return -1;

//     len = strlen(key);
//     index = (int)key[0];
//     for (i = 1; i<len; ++i) {
//         index *= 1103515245 + (int)key[i];
//     }
//     index >>= 27;
//     index &= (CMD_LIST_SIZE - 1);
//     return index;
// }

// //向哈希表中插入数据
// int insertEntry(table* t , const char* key , const char* value)
// {
//     int index , vlen1 , vlen2;
//     entry* e , *ep;

//     if (t == NULL || key == NULL || value == NULL) {
//         return -1;
//     }

//     index = keyToIndex(key);
//     if (t->bucket[index].key == NULL) {
//         t->bucket[index].key = strdup(key);
//         t->bucket[index].value = strdup(value);
//     }
//     else {
//         e = ep = &(t->bucket[index]);
//         while (e != NULL) { //先从已有的找
//             if (strcmp(e->key , key) == 0) {
//                 //找到key所在，替换值
//                 vlen1 = strlen(value);
//                 vlen2 = strlen(e->value);
//                 if (vlen1 > vlen2) {
//                     free(e->value);
//                     e->value = (char*)malloc(vlen1 + 1);
//                 }
//                 memcpy(e->value , value , vlen1 + 1);
//                 return index;   //插入完成了
//             }
//             ep = e;
//             e = e->next;
//         } // end while(e...

//         //没有在当前桶中找到
//         //创建条目加入
//         e = (entry*)malloc(sizeof (entry));
//         e->key = strdup(key);
//         e->value = strdup(value);
//         e->next = NULL;
//         ep->next = e;
//     }
//     return index;
// }

// //在哈希表中查找key对应的value
// //找到了返回value的地址，没找到返回NULL
// const char* findValueByKey(const table* t , const char* key)
// {
//     int index;
//     const entry* e;
//     if (t == NULL || key == NULL) {
//         return NULL;
//     }
//     index = keyToIndex(key);
//     e = &(t->bucket[index]);
//     if (e->key == NULL) return NULL;//这个桶还没有元素
//     while (e != NULL) {
//         if (0 == strcmp(key , e->key)) {
//             return e->value;    //找到了，返回值
//         }
//         e = e->next;
//     }
//     return NULL;
// }

// //在哈希表中查找key对应的entry
// //找到了返回entry，并将其从哈希表中移除
// //没找到返回NULL
// entry* removeEntry(table* t , char* key)
// {
//     int index;
//     entry* e,*ep;   //查找的时候，把ep作为返回值
//     if (t == NULL || key == NULL) {
//         return NULL;
//     }
//     index = keyToIndex(key);
//     e = &(t->bucket[index]);
//     while (e != NULL) {
//         if (0 == strcmp(key , e->key)) {
//             //如果是桶的第一个
//             if (e == &(t->bucket[index])) {
//                 //如果这个桶有两个或以上元素
//                 //交换第一个和第二个，然后移除第二个
//                 ep = e->next;
//                 if (ep != NULL) {
//                     entry tmp = *e; //做浅拷贝交换
//                     *e = *ep;//相当于链表的头节点已经移除
//                     *ep = tmp;  //这就是移除下来的链表头节点
//                     ep->next = NULL;
//                 }
//                 else {//这个桶只有第一个元素
//                     ep = (entry*)malloc(sizeof(entry));
//                     *ep = *e;
//                     e->key = e->value = NULL;
//                     e->next = NULL;
//                 }
//             }
//             else {
//                 //如果不是桶的第一个元素
//                 //找到它的前一个(这是前面设计不佳导致的多余操作)
//                 ep = &(t->bucket[index]);
//                 while (ep->next != e)ep = ep->next;
//                 //将e从中拿出来
//                 ep->next = e->next;
//                 e->next = NULL;
//                 ep = e;
//             }
//             return ep;
//         }// end if(strcmp...
//         e = e->next;
//     }
//     return NULL;
// }

// void printTable(table* t)
// {
//     int i;
//     entry* e;
//     if (t == NULL)return;
//     for (i = 0; i<CMD_LIST_SIZE; ++i) {
//         printf("\nbucket[%d]:\n" , i);
//         e = &(t->bucket[i]);
//         while (e->key != NULL) {
//             printf("\t%s\t=\t%s\n" , e->key , e->value);
//             if (e->next == NULL)break;
//             e = e->next;
//         }
//     }
// }